using NCP.Core.IoC;
using System;
using System.Collections.Generic;
using System.Reflection;
using Unity;
using Unity.Interception;
using Unity.Interception.Interceptors.TypeInterceptors.VirtualMethodInterception;
using Unity.Lifetime;

namespace WebApp
{
    /// <summary>
    /// Specifies the Unity configuration for the main container.
    /// </summary>
    public static class UnityConfig
    {
        #region Unity Container
        private static Lazy<IUnityContainer> container =
          new Lazy<IUnityContainer>(() =>
          {
              var container = new UnityContainer();
              RegisterTypes(container);
              return container;
          });

        /// <summary>
        /// Configured Unity Container.
        /// </summary>
        public static IUnityContainer Container => container.Value;
        #endregion

        /// <summary>
        /// Registers the type mappings with the Unity container.
        /// </summary>
        /// <param name="container">The unity container to configure.</param>
        /// <remarks>
        /// There is no need to register concrete types such as controllers or
        /// API controllers (unless you want to change the defaults), as Unity
        /// allows resolving a concrete type even if it was not previously
        /// registered.
        /// </remarks>
        public static void RegisterTypes(IUnityContainer container)
        {
            container.AddNewExtension<Interception>();
            Assembly bizAssembly = Assembly.Load("NCP.Service");
            foreach (var t in bizAssembly.GetTypes())
            {
                if (typeof(IService).IsAssignableFrom(t))
                    container.RegisterType(t, new PerThreadLifetimeManager()).Configure<Interception>().SetDefaultInterceptorFor(t, new VirtualMethodInterceptor());

            }
        }

        public static T Resolve<T>()
        {
            return Container.Resolve<T>();
        }

        public static IEnumerable<T> ResolveAll<T>()
        {
            return Container.ResolveAll<T>();
        }


        public static T Resolve<T>(string name)
        {
            return Container.Resolve<T>(name);
        }

        public static bool Contains<T>(string name)
        {
            return Container.IsRegistered<T>(name);
        }
    }
}